﻿Imports System.IO
Imports System.Drawing
Imports Microsoft.Win32

Public Module DCM_IO
    'Public Function Get_FileSize(FileName As String) As Long
    '    Return New FileInfo(FileName).Length
    'End Function
    Public Function 文件名自动加1修正(FS As String) As String
        Dim nf = DCM.Get_FileInfoFromFileName(FS)
        Dim FileFlage As Boolean = IO.File.Exists(FS)
        If FileFlage = True Then
            Dim LocalFileName = FS
            Dim NowFileNamei = 1
            Do While FileFlage
                LocalFileName = nf.路径 & "\" & nf.文件名 & "_" & NowFileNamei & If(nf.后缀名 = "", "", "." & nf.后缀名)
                FileFlage = IO.File.Exists(LocalFileName)
                NowFileNamei += 1
            Loop
            Return LocalFileName
        Else
            Return FS
        End If
    End Function
    Public Function 获取文件二进制字节(FilePathName As String) As Byte() '通过文件获取图片
        Using Fs As New System.IO.FileStream(FilePathName, IO.FileMode.Open, IO.FileAccess.Read)
            Dim Buff(Fs.Length - 1) As Byte
            Fs.Read(Buff, 0, Fs.Length - 1)
            Return Buff
        End Using
    End Function
    Public Function 获取文件二进制字节_转化为内存流(FilePathName As String) As MemoryStream '通过文件获取图片
        Dim memoryStream_start As New MemoryStream()
        Dim buff = 获取文件二进制字节(FilePathName)
        memoryStream_start.Write(buff, 0, buff.Length - 1)
        Return memoryStream_start
    End Function
    Public Function GetTxtFileString(TxtFileName As String) As String
        Using FS = New IO.StreamReader(TxtFileName, FileMode.Open)
            Return FS.ReadToEnd
        End Using
    End Function
    Public Function Fun_在指定文件目录中准备要写入的文件名(目录 As String, 文件名称 As String,
                                             Optional F_重复项强制重命名 As Boolean = False,
                                             Optional F_重复项强制覆盖 As Boolean = False,
                                             Optional F_重复的占用文件加TMP下载 As Boolean = False)
        DCM.File_检测文件夹是否存在(目录)
        Dim LocalFileName As String = 目录 & "\" & 文件名称
        Dim File_Name As String = 文件名称
        Dim FileFlage As Boolean = IO.File.Exists(LocalFileName)
        Dim NowFileNamei As Integer = 1
        If F_重复项强制重命名 Then
            If FileFlage = True Then
                Dim SL As Integer = InStrRev(File_Name, ".")
                Dim Name1 As String = "" '名称
                Dim Name2 As String = "" '后缀名
                If SL <> 0 Then
                    Name1 = Mid(File_Name, 1, SL - 1)
                    Name2 = Mid(File_Name, SL + 1)
                Else
                    Name1 = File_Name
                End If
                Do While FileFlage = True
                    File_Name = If(Name2 = "", Name1, Name1 & "(" & NowFileNamei & ")" & "." & Name2)
                    LocalFileName = 目录 & "\" & File_Name
                    FileFlage = IO.File.Exists(LocalFileName)
                    NowFileNamei += 1
                Loop
            End If
        Else
            If FileFlage = True Then
                'Dim RB As MsgBoxResult = MsgBoxResult.No
                'If F_重复项强制覆盖 = False Then
                '    RB = MsgBox("文件已经存在,是否覆盖:" & vbCrLf & LocalFileName, MsgBoxStyle.YesNo)
                'Else
                '    RB = MsgBoxResult.Yes
                'End If
                ' If RB = MsgBoxResult.Yes Then
                If F_重复项强制覆盖 Then
                    Dim IsHave = DCM.DCM_IO.IO_删除文件并直到判断文件消失为止(LocalFileName)
                    If IsHave = True Then
                        If F_重复的占用文件加TMP下载 = True Then
                            ' Dim File_Dir_This As String = dcm.DCM_IOFile.Get_返回完整路径的文件夹(SaveFileName, File_name_This)
                            Dim Local_FileName_tmp As String = LocalFileName & "tmp"
                            If DCM.IO_删除文件并直到判断文件消失为止(Local_FileName_tmp) = False Then
                                If IO.File.Exists(LocalFileName) = True Then
                                    Try
                                        File.Move(LocalFileName, Local_FileName_tmp)
                                    Catch ex As Exception
                                        Throw New Exception("文件更名为TMP失败:" & ex.Message & vbCrLf & LocalFileName)
                                    End Try
                                End If
                            Else
                                Throw New Exception("无法下载,因为文件无法被删除:" & Local_FileName_tmp)
                            End If
                        Else
                            Throw New Exception("删除文件失败,可能是该文件已经被占用:" & LocalFileName)
                        End If
                    End If
                End If
                'Else
                '    Throw New Exception("下载失败,文件已经存在:" & vbCrLf & LocalFileName)
                'End If
            End If
        End If
        Return LocalFileName
    End Function


    Public Function FileName_替换文件名危险字符(FileName As String, Optional 替换字符 As String = "_") As String
        Dim rs = FileName
        rs = rs.Replace("\", 替换字符)
        rs = rs.Replace("/", 替换字符)
        rs = rs.Replace(":", 替换字符)
        rs = rs.Replace("*", 替换字符)
        rs = rs.Replace("?", 替换字符)
        rs = rs.Replace("""", 替换字符)
        rs = rs.Replace("<", 替换字符)
        rs = rs.Replace(">", 替换字符)
        rs = rs.Replace("|", 替换字符)
        Return rs
    End Function
    Public Function CheckFileName_是否含有危险字符(FileName As String) As Boolean
        CheckFileName_是否含有危险字符_子过程(FileName, "/")
        CheckFileName_是否含有危险字符_子过程(FileName, "'")
        Return True
    End Function
    Private Sub CheckFileName_是否含有危险字符_子过程(FileName As String, CheckStr As String)
        If InStr(FileName, CheckStr) > 0 Then
            Throw New Exception("错误:文件名" & FileName & vbCrLf & "含有危险字符" & vbCrLf & CheckStr)
        End If
    End Sub
    Public Function HeBing文件名称和后缀名(文件名 As String, 后缀名 As String)
        If 后缀名 = "" Then Return 文件名
        Return 文件名 & "." & 后缀名
    End Function
    Public Function FormatLongToFileSize(ByVal Size As Double) As String
        Dim B As Double, M As Double, G As Double, T As Double, K As Double
        T = Size \ 1024 ^ 4

        'If T > 0 Then Return Val(String.Format(Size / 1024 ^ 4, "0.00")) & " TB"
        If T > 0 Then Return String.Format("{0:0.##}", Size / 1024 ^ 4) & " TB"

        G = (Size - T * 1024 ^ 4) \ 1024 ^ 3
        'If G > 0 Then Return Val(Format((Size - T * 1024 ^ 4) / 1024 ^ 3, "0.00")) & " GB"
        If G > 0 Then Return String.Format("{0:0.##}", (Size - T * 1024 ^ 4) / 1024 ^ 3) & " GB"

        M = (Size - T * 1024 ^ 4 - G * 1024 ^ 3) \ 1024 ^ 2
        If M > 0 Then Return String.Format("{0:0.##}", (Size - T * 1024 ^ 4 - G * 1024 ^ 3) / 1024 ^ 2) & " MB"

        K = (Size - T * 1024 ^ 4 - G * 1024 ^ 3 - M * 1024 ^ 2) \ 1024
        If K > 0 Then Return String.Format("{0:0.##}", (Size - T * 1024 ^ 4 - G * 1024 ^ 3 - M * 1024 ^ 2) / 1024) & " KB"

        B = Size - T * 1024 ^ 4 - G * 1024 ^ 3 - M * 1024 ^ 2 - K * 1024
        If B > 0 Then Return String.Format("{0:0.##}", Size - T * 1024 ^ 4 - G * 1024 ^ 3 - M * 1024 ^ 2 - K * 1024) & "  B"

        Return Size.ToString
    End Function
    'Public Function CreateTemporaryFileName(name As [String], IsFolder As Boolean) As [String]
    '    Dim path = System.IO.Path.GetTempPath()
    '    Dim fileName As [String]
    '    fileName = System.IO.Path.Combine(path, name)
    '    If IsFolder Then
    '        If System.IO.Directory.Exists(fileName) Then
    '            System.IO.Directory.Delete(fileName, True)
    '        End If
    '        If System.IO.File.Exists(fileName) Then
    '            System.IO.File.Delete(fileName)
    '        End If
    '        System.IO.Directory.CreateDirectory(fileName)
    '    Else
    '        Using file As System.IO.StreamWriter = New System.IO.StreamWriter(fileName)
    '            file.Close()
    '        End Using
    '    End If
    '    Return fileName
    'End Function
    Public Structure Get_FileName_名称扩展名
        Public 文件名 As String
        Public 后缀名 As String
        Public 路径 As String
        Public 文件大小 As Long
        Public 文件全名 As String
        Public 创建日期 As Date
        Public 修改日期 As Date
    End Structure
    Public Structure Get_FileName_路径名称
        Public 文件夹名 As String
        Public 路径 As String
    End Structure
    Public Function Get_FileInfoFromFolder(Folder As String) As Get_FileName_路径名称
        Folder = Folder.Replace("/", "\")
        If Folder.EndsWith("\") Then Folder = Mid(Folder, 1, Folder.Length - 1)
        Dim Rs As New Get_FileName_路径名称
        '第一步取出路径
        Dim R_路径标记 As Integer = InStrRev(Folder, "\")
        Dim FileName_NoPath As String = ""
        If R_路径标记 = 0 Then
            FileName_NoPath = Folder
        Else
            Rs.路径 = Left(Folder, R_路径标记 - 1)
            FileName_NoPath = Mid(Folder, R_路径标记 + 1)
        End If
        Rs.文件夹名 = FileName_NoPath
        Return Rs
    End Function
    Public Function Get_FileInfoFromFileName(FileName As String, Optional IsNeedGetFileSize As Boolean = False,
                                             Optional IsNeedGetCreateDate As Boolean = False,
                                             Optional IsNeedGetEditDate As Boolean = False) As Get_FileName_名称扩展名

        ' FileName = FileName.Replace("/", "\")
        FileName = FileName.Replace("\", "/")
        Dim Rs As New Get_FileName_名称扩展名
        '第一步取出路径
        Dim R_路径标记 As Integer = InStrRev(FileName, "/")
        Dim FileName_NoPath As String = ""
        If R_路径标记 = 0 Then
            FileName_NoPath = FileName
        Else
            Rs.路径 = Left(FileName, R_路径标记 - 1)
            FileName_NoPath = Mid(FileName, R_路径标记 + 1)
        End If
        Rs.文件全名 = FileName_NoPath
        '第二步,取出文件名和后缀
        Dim R_点 As Integer = InStrRev(FileName_NoPath, ".")
        ' If R_点 < R_路径标记 Then R_点 = 0
        If R_点 = 0 Then
            Rs.文件名 = FileName_NoPath
            Rs.后缀名 = ""
        Else
            Rs.文件名 = Left(FileName_NoPath, R_点 - 1)
            Rs.后缀名 = Mid(FileName_NoPath, R_点 + 1)
        End If
        Try
            Dim FI As New FileInfo(FileName)
            '文件大小
            If IsNeedGetFileSize Then
                If IO.File.Exists(FileName) = True Then Rs.文件大小 = FI.Length
            End If
            '创建日期
            If IsNeedGetCreateDate Then
                If IO.File.Exists(FileName) Or IO.Directory.Exists(FileName) Then Rs.创建日期 = FI.CreationTime
            End If
            '修改日期
            If IsNeedGetCreateDate Then
                If IO.File.Exists(FileName) Or IO.Directory.Exists(FileName) Then Rs.修改日期 = FI.LastWriteTime
            End If
        Catch ex As Exception
        End Try
        Return Rs
    End Function



    Public Function Get_FileNameFormOFD() As String
        Dim filter As String = "*.*|*.*"
        Return Get_FileNameFormOFD(filter)
    End Function

    Public Function Get_FileSize(FileName As String) As Long
        Return New FileInfo(FileName).Length
    End Function


    ''' <summary>
    '''删除成功返回false
    ''' </summary>
    ''' <param name="FileName"></param>
    ''' <param name="TimeOut"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IO_删除文件并直到判断文件消失为止(FileName As String, Optional TimeOut As Integer = 5) As Boolean
        Dim IsSuccess As Boolean = True
        Dim T_End = Now + TimeSpan.FromSeconds(TimeOut)
        Dim Err As String = ""
        Try
            IsSuccess = IO.File.Exists(FileName)
            Do While IsSuccess And T_End >= Now
                Try
                    System.IO.File.Delete(FileName)
                Catch ex As Exception
                    Err = ""
                End Try
                IsSuccess = IO.File.Exists(FileName)
                If IsSuccess = True Then Threading.Thread.Sleep(100)
            Loop
        Catch ex As Exception
        End Try
        Return IsSuccess
    End Function



    Public Function Get_返回目录下所有文件(Dir As String, Optional IS_寻找子目录 As Boolean = False, Optional IS_包含目录信息 As Boolean = False) As List(Of String)
        Dim Files As New List(Of String)
        If IO.Directory.Exists(Dir) = False Then Throw New Exception("无法找到文件夹:" & Dir)
        If IS_寻找子目录 Then
            If IS_包含目录信息 Then
                Dim FS1() As String = IO.Directory.GetFileSystemEntries(Dir)
                Files.AddRange(FS1)
            Else
                Dim FS1() As String = IO.Directory.GetFiles(Dir)
                Files.AddRange(FS1)
            End If
            For Each Dir子 As String In IO.Directory.GetDirectories(Dir)
                Get_返回目录下所有文件_子(Files, Dir子, IS_包含目录信息)
            Next
        Else
            If IS_包含目录信息 Then
                Dim FS1() As String = IO.Directory.GetFileSystemEntries(Dir)
                Files.AddRange(FS1)
            Else
                Dim FS1() As String = IO.Directory.GetFiles(Dir)
                Files.AddRange(FS1)
            End If
        End If
        Return Files
    End Function
    Private Sub Get_返回目录下所有文件_子(Files As List(Of String), Dir As String, IS_包含目录信息 As Boolean)
        If IS_包含目录信息 Then
            Dim FS1() As String = IO.Directory.GetFileSystemEntries(Dir)
            Files.AddRange(FS1)
        Else
            Dim FS1() As String = IO.Directory.GetFiles(Dir)
            Files.AddRange(FS1)
        End If
        For Each Dir子 As String In IO.Directory.GetDirectories(Dir)
            Get_返回目录下所有文件_子(Files, Dir子, IS_包含目录信息)
        Next
    End Sub


    Public Property Xml_GetAndSet(ByVal XMLPath As String, ByVal NodeName As String, Optional NullReturnStr As String = "") As String
        Get
            Dim xmlDoc As New Xml.XmlDocument()
            If IO.File.Exists(XMLPath) = False Then
                Dim XmlWrite As System.Xml.XmlTextWriter = New System.Xml.XmlTextWriter(XMLPath, System.Text.Encoding.UTF8)
                XmlWrite.WriteStartDocument() '开始一个文档
                XmlWrite.WriteStartElement("Main") '开始一个元素,根元素
                XmlWrite.WriteEndElement() '关闭元素root
                XmlWrite.WriteEndDocument() '文档结束
                XmlWrite.Flush() '刷新
                XmlWrite.Close() '关闭
            End If
            xmlDoc.Load(XMLPath)
            Dim root As Xml.XmlNode = xmlDoc.SelectSingleNode("Main") '查找<root> 
            If IsNothing(root) = True Then
                Throw New Exception("Main节点不存在，无法创建子节点！")
            End If
            Dim nodeList As Xml.XmlNodeList = root.ChildNodes '获取root节点的所有子节点 
            Dim xn As Xml.XmlNode
            For Each xn In nodeList '遍历所有子节点 
                If xn.Name = NodeName Then
                    ' 找到节点后返回
                    Return xn.InnerText
                End If
            Next xn
            Return ""
        End Get
        Set(value As String)
            Dim xmlDoc As New Xml.XmlDocument()
            If IO.File.Exists(XMLPath) = False Then
                Dim XmlWrite As System.Xml.XmlTextWriter = New System.Xml.XmlTextWriter(XMLPath, System.Text.Encoding.UTF8)
                XmlWrite.WriteStartDocument() '开始一个文档
                XmlWrite.WriteStartElement("Main") '开始一个元素,根元素
                XmlWrite.WriteEndElement() '关闭元素root
                XmlWrite.WriteEndDocument() '文档结束
                XmlWrite.Flush() '刷新
                XmlWrite.Close() '关闭
            End If
            xmlDoc.Load(XMLPath)
            Dim root As Xml.XmlNode = xmlDoc.SelectSingleNode("Main") '查找<root> 
            If IsNothing(root) = True Then
                Throw New Exception("Main节点不存在，无法创建子节点！")
            End If
            Dim nodeList As Xml.XmlNodeList = root.ChildNodes '获取root节点的所有子节点 
            Dim xn As Xml.XmlNode
            For Each xn In nodeList '遍历所有子节点 
                If xn.Name = NodeName Then
                    '找到节点后修改
                    xn.InnerText = value
                    xmlDoc.Save(XMLPath)
                    Return
                End If
            Next xn
            '到此未返回说明需要创建
            Dim XE As Xml.XmlElement = xmlDoc.CreateElement(NodeName)
            XE.InnerText = value
            root.AppendChild(XE)
            xmlDoc.Save(XMLPath)
            Return
        End Set
    End Property


    Public Const OF_READWRITE As Integer = 2
    Public Const OF_SHARE_DENY_NONE As Integer = &H40
    Public ReadOnly HFILE_ERROR As New IntPtr(-1)

    ''' <summary>
    ''' 原CheckDir
    ''' </summary>
    ''' <param name="DirPath"></param>
    ''' <remarks></remarks>
    Public Sub File_检测文件夹是否存在(ByVal DirPath As String)
        DirPath = File_修正平台文件路径(DirPath)
        If IO.Directory.Exists(DirPath) = False Then
            IO.Directory.CreateDirectory(DirPath)
        End If
    End Sub
    Public Function File_修正平台文件路径(ByVal FileName As String) As String
        FileName = FileName.Replace("/", Path.DirectorySeparatorChar)
        FileName = FileName.Replace("\", Path.DirectorySeparatorChar)
        Return FileName
    End Function
    Public Function File_检测文件是否存在(ByVal FileName As String) As Boolean
        FileName = File_修正平台文件路径(FileName)
        Return IO.File.Exists(FileName)
    End Function
    Public Function CheckAndSaveFile(ByVal MyPath As String) As String
        Try
            MyPath.Replace("/", "\")
            Dim in2 As Integer = InStrRev(MyPath, "\")
            If in2 = 0 Then
                Throw New Exception("路径中未找到\,无法处理!")
            Else
                File_检测文件夹是否存在(Mid(MyPath, 1, in2))
            End If
            Dim _SaveFileName As String = Mid(MyPath, in2 + 1)
            Dim _SaveFilePath As String = Mid(MyPath, 1, in2 - 1)
            Dim FileFlage As Boolean = IO.File.Exists(MyPath)
            Dim NowFileNamei As Integer = 1
            If FileFlage = True Then
                Dim SL As Integer = InStrRev(_SaveFileName, ".")
                Dim Name1 As String = "" '名称
                Dim Name2 As String = "" '后缀名
                If SL <> 0 Then
                    Name1 = Mid(_SaveFileName, 1, SL - 1)
                    Name2 = Mid(_SaveFileName, SL + 1)
                Else
                    Name1 = _SaveFileName
                End If
                Do While FileFlage = True
                    _SaveFileName = If(Name2 = "", Name1, Name1 & "(" & NowFileNamei & ")" & "." & Name2)
                    MyPath = _SaveFilePath & _SaveFileName
                    FileFlage = IO.File.Exists(MyPath)
                    NowFileNamei += 1
                Loop
            End If
            Return MyPath
        Catch ex As Exception
            Throw ex
        End Try
    End Function
    Public Sub Fold_检查并打开文件夹(FolderPath As String)
        File_检测文件夹是否存在(FolderPath)
        Process.Start(FolderPath)
    End Sub


End Module
